package cn.moondev.game.entity;

import cn.moondev.game.exce.GameException;

/**
 * 矩阵，封装了生命游戏的基本算法
 * @author scchen
 * @date   2015年11月17日
 */
public class Matrix {

    /**
     * 矩阵的行数
     */
    private int row;
    
    /**
     * 矩阵的列数
     */
    private int column;
    
    /**
     * 矩阵中的细胞,使用二维数组存放
     */
    private Cell[][] cells;
    
    public Matrix(int row,int column) {
        this.row = row;
        this.column = column;
        this.cells = new Cell[row][column];
        for(int i=0;i<row;i++) {
            for(int j=0;j<column;j++) {
                cells[i][j] = new Cell();
            }
        }
    }
    
    /**
     * 激活矩阵中的某个细胞
     * @param row       细胞在矩阵水平方向的位置
     * @param column    细胞在矩阵垂直方向的位置
     */
    public void activateCell(int row,int column) {
        if(row < 0 || row >= this.row || column < 0 || column >= this.column) {
            throw new GameException("你要激活的细胞位置已经超出矩阵边界,请检查后重试");
        }
        Cell cell = this.cells[row][column];
        cell.setState(State.ALIVE);
        // 激活某个细胞，那么这个细胞周围的8个细胞的aliveNeighborNum需要加1
        plusAliveNeighborNum(row,column);
    }
    
    /**
     * 指定细胞周围的8(考虑边界问题，有可能小于8)个细胞的aliveNeighborNum++
     * @param row       细胞在矩阵水平方向的位置
     * @param column    细胞在矩阵垂直方向的位置
     */
    public void plusAliveNeighborNum(int row,int column) {
        plusAliveNeighborNum(this.cells,row,column);
    }
    
    /**
     * 指定细胞周围的8(考虑边界问题，有可能小于8)个细胞的aliveNeighborNum++
     * @param row       细胞在矩阵水平方向的位置
     * @param column    细胞在矩阵垂直方向的位置
     */
    public void plusAliveNeighborNum(Cell[][] copy,int row,int column) {
        for(int i=-1;i<=1;i++) {
            for(int j=-1;j<=1;j++) {
                if(row + i < 0 || row + i >= this.row || column + j < 0 || column + j >= this.column) {
                    continue;
                }
                if(i==0 && j==0) {
                    continue;
                }
                copy[row + i][column + j].plusAliveNeighborNum();
            }
        }
    }
    
    /**
     * 判断下一代还存活的细胞
     */
    public Matrix judgeNextGeneration() {
        // 创建矩阵的下一代
        Matrix matrix = new Matrix(row,column);
        Cell[][] next = matrix.getCells(); 
        for(int i=0;i<row;i++) {
            for(int j=0;j<column;j++) {
                Cell cell = this.cells[i][j];
                State state = cell.getState().judge(cell.getAliveNeighborNum());
                // 修改下一代中细胞的状态
                next[i][j].setState(state);
                if(state == State.ALIVE) {
                    plusAliveNeighborNum(next,i,j);
                }
            }
        }
        return matrix;
    }

    public Cell[][] getCells() {
        return cells;
    }
}
